<template>
  <div class="upload-file-uploader" :style="{ '--min-height': height }">
    <div class="overlay" v-if="!multiple && loading" v-for="x in fileList">
      <el-icon
        size="24"
        class="cursor-pointer"
        @click="handleRemove(x, fileList)"
      >
        <CircleClose />
      </el-icon>
      <el-progress
        width="180"
        type="circle"
        color="var(--el-color-primary)"
        :format="(val: number) => Math.round(val) + '%'"
        :percentage="x.percentage || 0"
      ></el-progress>
    </div>
    <el-upload
      ref="refUpload"
      drag
      :accept="accept"
      :multiple="multiple"
      :limit="limit"
      :http-request="handleBeforeUpload"
      :file-list="fileList"
      :on-progress="handleProgress"
      :on-success="handleSuccess"
      :on-error="handleError"
      :on-change="handleChange"
      :on-remove="handleRemove"
      :show-file-list="false"
    >
      <template v-if="fileList.length && !multiple">
        <template v-for="x in fileList">
          <template v-if="isPdfUrl(x.fileName) || isPdfUrl(x.type)">
            <img src="@/assets/icons/pdf.png" class="w-[100px] mb-4" />
            <div class="text-[#222] text-base">{{ x.fileName }}</div>
          </template>
          <template v-else-if="isAudioUrl(x.fileName) || isAudioUrl(x.type)">
            <img src="@/assets/icons/mp3.png" class="w-[100px] mb-4" />
            <div class="text-[#222] text-base">{{ x.fileName }}</div>
          </template>
          <template v-else-if="isImageUrl(x.fileName) || isImageUrl(x.type)">
            <img src="@/assets/icons/jpg.png" class="w-[100px] mb-4" />
            <div class="text-[#222] text-base">{{ x.fileName }}</div>
          </template>
          <template v-else>
            <img src="@/assets/icons/mp4.png" class="w-[100px] mb-4" />
            <div class="text-[#222] text-base">{{ x.fileName }}</div>
          </template>
          <!--                    <el-image v-else-if="poster || isImageUrl(x.name)"-->
          <!--                              :src="poster || x.blobUrl || x.url"-->
          <!--                              :hide-on-click-modal="true"-->
          <!--                              :preview-teleported="true" fit="cover"-->
          <!--                              class="w-full h-auto block"-->
          <!--                              :preview-src-list="[poster || x.blobUrl || x.url]"/>-->
          <!--                    <video v-else controls show-play-btn :src="x.blobUrl || x.url"-->
          <!--                           class="w-full h-full block object-cover"/>-->
        </template>
      </template>
      <template v-else>
        <img src="@/assets/img_upload.png" alt="" class="w-[124px] h-auto" />
        <div class="el-upload__text pt-3">
          <div class="text-[#222] text-base" :class="{ 'pb-2': $slots.tip }">
            <slot name="upload-text">点击上传或将文件拖入此区域</slot>
          </div>
          <div class="text-center text-gray-400 text-sm" v-if="$slots.tip">
            <slot name="tip"></slot>
          </div>
        </div>
      </template>
    </el-upload>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref, reactive, computed, useSlots, nextTick } from "vue"
import type {
  UploadProps,
  UploadFile,
  UploadFiles,
  UploadRequestOptions,
} from "element-plus"
import { message } from "@/Hooks/Element-plus"
import * as qiniu from "qiniu-js"
import { getUpToken } from "@/api/utils"
import { generateUUID } from "@/utils/stringFun"
import piniaStore from "@/stores/index"
import { useUserStore } from "@/stores/modules/user"

const $slots = useSlots()
const userStore = useUserStore(piniaStore)

console.log(userStore.userinfo)

const props = defineProps({
  modelValue: [String, Array],
  poster: {
    type: String,
    default: null,
  },
  // 数量限制
  limit: {
    type: Number,
    default: 5,
  },
  // 大小限制(MB)
  fileSize: {
    type: [Number, Object],
    default: 5,
  },
  accept: {
    type: String,
    default: "video/*",
  },
  multiple: {
    type: Boolean,
    default: false,
  },
  height: {
    type: String,
    default: null,
  },
})

function getFileExt(url: string): string {
  const urlParts = url.split(/[\/.]/)
  return urlParts[urlParts.length - 1].toLowerCase()
}

function isImageUrl(url: string): boolean {
  const imageExtensions = ["jpg", "jpeg", "png", "gif", "bmp", "svg", "webp"]
  return imageExtensions.includes(getFileExt(url))
}

function isVideoUrl(url: string): boolean {
  const videoExtensions = ["mp4", "avi", "mov", "wmv", "flv", "mkv"]
  return videoExtensions.includes(getFileExt(url))
}

function isPdfUrl(url: string): boolean {
  const pdfExtensions = ["pdf"]
  return pdfExtensions.includes(getFileExt(url))
}

function isAudioUrl(url: string): boolean {
  const audioExtensions = ["mp3", "wav", "ogg", "aac"]
  return audioExtensions.includes(getFileExt(url))
}

const poster = ref()
const refUpload = ref()
const loading = ref(false)
const fileData: any = {}
const fileList = ref([] as UploadFiles)
const emit = defineEmits(["update:modelValue", "change", "on-success"])
const handleBeforeUpload = async (options: UploadRequestOptions) => {
  const file = options.file as any
  let fileSize = props.fileSize

  // 根据文件类型设置大小限制
  if (typeof fileSize === "object") {
    if (isImageUrl(file.name)) {
      fileSize = fileSize.image
    } else if (isVideoUrl(file.name)) {
      fileSize = fileSize.video
    } else {
      fileSize = fileSize.audio
    }
  }

  fileSize = Number(fileSize)
  if (file.size > fileSize * 1024 * 1024) {
    if (fileSize >= 1024) {
      options.onError(`文件大小超过限制${fileSize / 1024}GB` as any)
    } else {
      options.onError(`文件大小超过限制${fileSize}MB` as any)
    }
    return false
  }

  try {
    if (!props.multiple) {
      fileList.value = []
    }
    file.percentage = 0
    file.status = "ready"
    file.fileName = file.name
    file.blobUrl = URL.createObjectURL(file)
    loading.value = true
    const data = await getUpToken()
    const config = {
      useCdnDomain: true,
      region: data.region || null,
      // chunkSize: 4,//默认4Mb
    }
    const upToken = data.upToken
    const putExtra = { fname: file.name }
    const fileExt = file.type.split("/")[1]
    const fileKey =
      `${data.dir}/${userStore.userinfo.userId}/` +
      generateUUID().replace(/-/g, "") +
      fileExt
    const observable = qiniu.upload(file, fileKey, upToken, putExtra, config)
    const subscription = observable.subscribe({
      next(res: any) {
        res.percentage = res.total?.percent || 0
        file.percentage = res.percentage
        file.status = "uploading"
        console.log(res)
        options.onProgress(res)
      },
      error(error: any) {
        file.errMsg = error
        file.status = "fail"
        options.onError(error)
      },
      complete(res: any) {
        file.status = "success"
        console.log("uploaded", res)
        options.onSuccess(res)
      },
    })

    // 添加到文件列表
    fileList.value.push(file as any)

    //缓存取消上传
    fileData[file.uid] = {
      abort: () => {
        console.log("unsubscribe")
        subscription.unsubscribe()
      },
    }
  } catch (error) {
    console.log(error)
    options.onError(error as any)
  }
}

const handleChange: UploadProps["onChange"] = (file) => {
  // 处理文件改变的回调
  // console.log('handleChange', file, fileList.length);
  file.status = "uploading"
  loading.value = true
}

const handleProgress: UploadProps["onProgress"] = (event) => {
  // 处理上传进度的回调
  // console.log(event);
  loading.value = true
}

const handleSuccess = async (response: any, file: any) => {
  // 处理上传成功的回调
  console.log(response)
  if (response?.key) {
    console.log(response, file, fileList)
    const fileUrl = response.key
    // poster.value = await getCover(file);
    // const coverUrl = fmtFileName(poster.value);
    // console.log('coverUrl', coverUrl);
    if (props.multiple) {
      file.fileUrl = fileUrl
      // file.cover = coverUrl;
      emit("change", file)
    } else {
      // emit('update:poster', coverUrl)
      emit("update:modelValue", fileUrl)
    }
    file.status = "success"
    message("success", "上传成功")
  }
  await nextTick(() => {
    loading.value = false
  })
}

const handleError: UploadProps["onError"] = (error: any, file: any) => {
  file.status = "fail"
  loading.value = false
  if (error.toString().includes('"msg":')) {
    file.errMsg = error.toString().split('"msg":"')[1].split('",')[0]
  } else {
    file.errMsg = error || "上传失败"
  }
  console.log(error, file)
  if (!props.multiple) {
    message("error", file.errMsg)
  }
}

const handleRemove: UploadProps["onRemove"] = (file: any) => {
  // 处理文件移除的回调
  console.log("handleRemove", file)
  fileData[file.uid]?.abort()
  fileList.value.splice(fileList.value.indexOf(file), 1)
}
</script>

<style lang="scss" scoped>
.upload-file-uploader {
  position: relative;
  overflow: hidden;
  background: #f5f7fa;
  border: 2px dotted #ced3db;
  border-radius: 7px;

  --el-fill-color-blank: #f5f7fa;
  --el-text-color-regular: #fff;

  :deep(.el-upload) {
    .el-upload-dragger {
      display: flex;
      flex-flow: column;
      align-items: center;
      justify-content: center;
      min-height: var(--min-height, 240px);
      max-height: var(--min-height, 40vh);
    }
  }

  .overlay {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    background-color: rgb(10 10 10 / 40%);

    .el-icon {
      position: absolute;
      top: 10px;
      right: 10px;
      z-index: 2;
      color: #fff;
    }
  }
}
</style>
